home *** CD-ROM | disk | FTP | other *** search
- /* insert.c */
-
- /* JOVE/MSDOS. K. Mitchum 1/85 */
- /* Modifications for personal use only. */
- /* original code J. Payne LSRHS 5/83 */
- /* Ken Mitchum */
- /* University of Pittsburgh */
- /* Decision Systems Laboratory */
-
-
- /*
- Jonathan Payne at Lincoln-Sudbury Regional High School 5/25/83
-
- Insert routines: the routine to Yank from the kill buffer
- and to insert lines, and characters into the buffer. */
-
- #include "jove.h"
-
- extern int RMargin;
-
-
-
- #define CHUNKSIZE 40
-
- /* Make a newline after `after' or course in `buf' */
-
- LINE *
- listput(buf, after)
- BUFFER *buf;
- LINE *after;
- {
- LINE *newline = nbufline();
-
- if (after == 0) { /* First line in this list */
- buf->b_zero = buf->b_dol = buf->b_dot = newline;
- newline->l_next = newline->l_prev = 0;
- return newline;
- }
- newline->l_prev = after;
- newline->l_next = after->l_next;
- after->l_next = newline;
- if (newline->l_next)
- newline->l_next->l_prev = newline;
- else
- if (buf)
- buf->b_dol = newline;
- return newline;
- }
-
- /* Global variables aren't that bad. There is a point where one
- * can go too far in trying to eliminate global variables on a
- * principle. After all this isn't LISP or anything like that.
- */
-
- LineInsert()
- {
- register int num = exp;
- char newline[LBSIZE];
- LINE *newdot,
- *olddot = curline;
- int oldchar = curchar;
- int atbegin = (!firstp(curline) && bolp());
-
- exp = 1;
- if (atbegin) /* This is mostly to make redisplay seem smart
- but it also decreases the amount of copying
- from one buffer to another */
- BackChar();
- strcpy(newline, &linebuf[curchar]);
-
- newdot = curline;
- while (num--) {
- newdot = listput(curbuf, newdot); /* Put after newdot */
- newdot->l_dline = putline("") | DIRTY;
- }
- linebuf[curchar] = '\0'; /* Shorten this line */
- SavLine(curline, linebuf);
- makedirty(curline);
- curline = newdot;
- curchar = 0;
- strcpy(linebuf, newline);
- makedirty(curline);
- if (atbegin)
- ForChar();
- SetModified(curbuf);
- IFixMarks(olddot, oldchar, curline, curchar);
- }
-
- LineAI()
- {
- LineInsert();
- whitesp(getline(curline->l_prev->l_dline, genbuf), linebuf);
- }
-
- whitesp(from, to)
- register char *from,
- *to;
- {
- char c;
- int oldchar = curchar;
-
- while ((c = *from++) && (c == ' ' || c == '\t'))
- insert(c, to, curchar++, 1, LBSIZE);
- SetModified(curbuf);
- IFixMarks(curline, oldchar, curline, curchar);
- }
-
- len_error(flag)
- {
- char *mesg = "line too long";
-
- (flag == COMPLAIN) ? complain(mesg) : error(mesg);
- }
-
- /* Insert num number of c's at offset atchar in a linebuf of LBSIZE */
-
- insert(c, buf, atchar, num, max)
- char c, *buf;
- {
- register char *pp, *pp1;
- register int len = atchar + strlen(&buf[atchar]);
- int numchars; /* Number of characters to copy forward */
-
- if (len + num >= max)
- len_error(COMPLAIN);
- pp = &buf[len];
- pp1 = &buf[len + num];
- numchars = len - atchar;
- while (numchars-- >= 0)
- *pp1-- = *pp--;
- pp = &buf[atchar];
- while (num--)
- *pp++ = c;
- }
-
- /*
- * Three situations:
- *
- * (1) We are at the end of the line in which case we just insert the char.
- * (2) We are in the middle of the line on a normal character in which case
- * we replace that character with 'c'.
- * (3) We are in the middle of a tab. Here we insert the character unless
- * we are at the end of the tab stop in which case cover the tab with
- * 'c'.
- */
-
- OverWrite()
- {
- int i, num;
-
- for (i = 0, num = exp, exp = 1; i < num; i++) {
- if (!eolp())
- DelNChar();
- Insertc(LastKeyStruck);
- }
- }
-
- SelfInsert()
- {
- Insertc(LastKeyStruck);
- }
-
- Insertc(c)
- {
- SetModified(curbuf);
- makedirty(curline);
- insert(c, linebuf, curchar, exp, LBSIZE);
- IFixMarks(curline, curchar, curline, curchar + exp);
- curchar += exp;
- }
-
- /*
- * Tab in to the right place for c mode
- */
-
- CTab()
- {
- if (strlen(linebuf) == 0)
- c_indent();
- Insertc('\t');
- }
-
- QuotChar()
- {
- int c;
-
- if (c = (*Gtchar)())
- Insertc(c);
- }
-
- blankp(line)
- char *line;
- {
- register char c;
-
- while (c = *line++)
- if (c != ' ' && c != '\t')
- return 0;
- return 1;
- }
-
- /* Insert the paren. If in C mode and c is a '}' then insert the
- * '}' in the "right" place for C indentation; that is indented
- * the same amount as the matching '{' is indented.
- */
-
- DoParen()
- {
- BUFLOC *bp;
- int nomatch;
- int nx,
- c = LastKeyStruck;
- nomatch = 0;
- if (c != ')' && c != '}')
- complain((char *) 0);
- if (c == '}' && IsFlagSet(globflags, CMODE))
- if (blankp(linebuf)) {
- Bol(); /* Beginning of line and */
- DelWtSpace(); /* Delete white space */
- c_indent(); /* insert the white space */
- }
-
- Insertc(c);
- if (IsFlagSet(globflags, MATCHING)) {
- redisplay();
- GotoDot();
- BackChar();
- if (NotInQuotes(linebuf, curchar)) {
- if (bp = m_paren(c, curwind->w_top)) {
- nx = in_window(curwind, bp->p_line);
- if (nx != -1) {
- BUFLOC b;
-
- DOTsave(&b);
- SetDot(bp);
- redisplay();
- sleep(1);
- SetDot(&b);
- }
- } else nomatch++;
- }
- ForChar();
- }
- if(nomatch) complain("Match to %c not in window",c);
- return;
- }
-
- c_indent()
- {
- BUFLOC *bp;
-
- bp = m_paren('}', curbuf->b_zero);
- if (!bp)
- return;
- ignore(getright(bp->p_line, genbuf));
- whitesp(genbuf, linebuf);
- }
-
- AtMargin()
- {
- int open_kludge = 0;
-
- exp = 1;
-
- if (curline->l_next == 0) {
- OpenLine();
- open_kludge++;
- }
- DoJustify(curline, curline->l_next);
- if (open_kludge)
- DelNChar();
- }
-
- Newline()
- {
- /* If there is more than 2 blank lines in a row then don't make
- * a newline, just move down one.
- */
-
- if (exp == 1 && eolp() && curline->l_next &&
- (getline(curline->l_next->l_dline,
- genbuf)[0] == '\0') && curline->l_next->l_next &&
- (getline(curline->l_next->l_next->l_dline,
- genbuf)[0] == '\0')) {
- SetLine(curline->l_next);
- return;
- }
- LineInsert();
- }
-
- TextInsert()
- {
- Insertc(LastKeyStruck);
- if ((curchar > RMargin) && LastKeyStruck != ' ')
- AtMargin();
- }
-
- ins_str(str)
- register char *str;
- {
- register char c;
- int pos = curchar;
-
- while (c = *str++) {
- if (c == '\n')
- continue;
- insert(c, linebuf, curchar++, 1, LBSIZE);
- }
- IFixMarks(curline, pos, curline, curchar);
- makedirty(curline);
- }
-
- linecopy(onto, atchar, from)
- register char *onto, *from;
- register int atchar;
- {
- char *base = onto;
-
- onto += atchar;
-
- while (*onto = *from++)
- if (onto++ >= &base[LBSIZE - 2])
- len_error(ERROR);
- }
-
- OpenLine()
- {
- int num = exp;
-
- LineInsert(); /* Open the lines... */
- DoTimes(BackChar, num);
- }
-
- BUFLOC *
- DoYank(fline, fchar, tline, tchar, atline, atchar, whatbuf)
- LINE *fline, *tline, *atline;
- BUFFER *whatbuf;
- {
- register LINE *newline;
- static BUFLOC bp;
- char save[LBSIZE],
- buf[LBSIZE];
- LINE *startline = atline;
- int startchar = atchar;
-
- SetModified(curbuf);
- lsave();
- ignore(getright(atline, genbuf));
- strcpy(save, &genbuf[atchar]);
-
- ignore(getright(fline, buf));
- if (fline == tline)
- buf[tchar] = '\0';
-
- linecopy(genbuf, atchar, &buf[fchar]);
- atline->l_dline = putline(genbuf);
- makedirty(atline);
-
- fline = fline->l_next;
- while (fline != tline->l_next) {
- newline = listput(whatbuf, atline);
- newline->l_dline = fline->l_dline;
- makedirty(newline);
- fline = fline->l_next;
- atline = newline;
- atchar = 0;
- }
-
- ignore(getline(atline->l_dline, genbuf));
- atchar += tchar;
- linecopy(genbuf, atchar, save);
- atline->l_dline = putline(genbuf);
- makedirty(atline);
- IFixMarks(startline, startchar, atline, atchar);
- bp.p_line = atline;
- bp.p_char = atchar;
- this_cmd = YANKCMD;
- getDOT(); /* Whatever used to be in linebuf */
- return &bp;
- }
-
- /* This is an attempt to reduce the amount of memory taken up by each line.
- Without this each malloc of a line uses sizeof (LINE) + sizeof(HEADER)
- where LINE is 3 words and HEADER is 1 word.
- This is going to allocate memory in chucks of CHUNKSIZE * sizeof (LINE)
- and divide each chuck into LINES. A LINE is free in a chunk when its
- line->l_dline == 0, so linefree sets dline to 0. */
-
-
-
- struct chunk {
- int c_nlines; /* Number of lines in this chunk
- (so they don't all have to be CHUNKSIZE long) */
- LINE *c_block; /* Chunk of memory */
- struct chunk *c_nextfree; /* Next chunk of lines */
- };
-
- struct chunk *fchunk = 0;
-
- LINE *ffline = 0; /* First free line */
-
- freeline(line)
- register LINE *line;
- {
- line->l_dline = 0;
- line->l_next = ffline;
- if (ffline)
- ffline->l_prev = line;
- line->l_prev = 0;
- ffline = line;
- }
-
- lfreelist(first)
- register LINE *first;
- {
- if (first)
- lfreereg(first, lastline(first));
- }
-
- /* Append region from line1 to line2 onto the free list of lines */
-
- lfreereg(line1, line2)
- register LINE *line1,
- *line2;
- {
- register LINE *next,
- *last = line2->l_next;
-
- while (line1 != last) {
- next = line1->l_next;
- freeline(line1);
- line1 = next;
- }
- }
-
- newchunk()
- {
- register LINE *newline;
- register int i;
- struct chunk *f;
- int nlines = CHUNKSIZE;
-
- f = (struct chunk *) malloc((unsigned) sizeof (struct chunk));
- if (f == 0)
- return 0;
- while (nlines > 0) {
- f->c_block = (LINE *) malloc((unsigned) (sizeof (LINE) * nlines));
- if (f->c_block != 0)
- break;
- nlines /= 2;
- }
- if (nlines <= 0)
- return 0;
-
- f->c_nlines = nlines;
- for (i = 0, newline = f->c_block; i < nlines; newline++, i++)
- freeline(newline);
- f->c_nextfree = fchunk;
- fchunk = f;
- return 1;
- }
-
- LINE *
- nbufline()
- {
- register LINE *newline;
-
- if (ffline == 0) { /* No free list */
- if (newchunk() == 0)
- complain("out of lines");
- }
- newline = ffline;
- ffline = ffline->l_next;
- if (ffline)
- ffline->l_prev = 0;
- return newline;
- }
-
- /* Remove the free lines in chunk c from the free list because they are
- no longer free. */
-
- remfreelines(c)
- register struct chunk *c;
- {
- register LINE *lp;
- register int i;
-
- for (lp = c->c_block, i = 0; i < c->c_nlines; i++, lp++) {
- if (lp->l_prev)
- lp->l_prev->l_next = lp->l_next;
- else
- ffline = lp->l_next;
- if (lp->l_next)
- lp->l_next->l_prev = lp->l_prev;
- }
- }
-
- /* This is/{should be} used to garbage collect the chunks of lines when
- malloc fails and we are NOT looking for a new buffer line. This goes
- through each chunk, and if every line in a given chunk is not allocated,
- the entire chunk is `free'd by "free()" */
-
- GCchunks()
- {
- register struct chunk *cp;
- struct chunk *prev = 0,
- *next = 0;
- register int i;
- register LINE *newline;
-
- message("Garbage collecting ...");
- UpdateMesg();
- #ifdef UNIX
- sleep(1);
- #endif
- for (cp = fchunk; cp; cp = next) {
- for (i = 0, newline = cp->c_block; i < cp->c_nlines; newline++, i++)
- if (newline->l_dline != 0)
- break;
-
- next = cp->c_nextfree;
-
- if (i == cp->c_nlines) { /* Unlink it!!! */
- if (prev)
- prev->c_nextfree = cp->c_nextfree;
- else
- fchunk = cp->c_nextfree;
- remfreelines(cp);
- free((char *) cp->c_block);
- free((char *) cp);
- } else
- prev = cp;
- }
- }
- DoBrace()
- {
- int c = LastKeyStruck;
- if (c != '{') complain((char *) 0);
- Insertc(c);
- if (IsFlagSet(globflags,CMODE)) {
- LineAI();
- CTab();
- }
- redisplay();
- }
-
-
-
-
-
-
- /*-----------------------------o.s. dependent------------------------*/
- #ifndef UNIX
- sleep(n)
- {
- int q;
- int p = gcsec() & 0xff;
- do {
- q = gcsec() &0xff;
- if(q < p) q +=100;
- }while ((q - p) < 50);
- }
- #endif
-
- /* end */